package com.atguigu.gmall.payment.service.impl;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.atguigu.gmall.common.constant.MqConst;
import com.atguigu.gmall.common.service.RabbitService;
import com.atguigu.gmall.model.enums.PaymentStatus;
import com.atguigu.gmall.model.enums.PaymentType;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.payment.PaymentInfo;
import com.atguigu.gmall.order.client.OrderFeignClient;
import com.atguigu.gmall.payment.mapper.PaymentInfoMapper;
import com.atguigu.gmall.payment.service.PaymentService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class PaymentServiceImpl implements PaymentService {

    @Autowired
    private PaymentInfoMapper paymentInfoMapper;

    @Autowired
    private OrderFeignClient orderFeignClient;

    @Autowired
    private AlipayClient alipayClient;

    @Autowired
    private PaymentService paymentService;

    @Autowired
    private RabbitService rabbitService;

    /**
     * 保存交易记录
     *
     * @param orderInfo
     * @param paymentType 支付类型（1：微信 2：支付宝）
     */
    @Override
    public void savePaymentInfo(OrderInfo orderInfo, String paymentType) {
//        判断是否重复提交支付数据
        QueryWrapper<PaymentInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("payment_type", paymentType);
        wrapper.eq("order_id", orderInfo.getId());
        Integer count = paymentInfoMapper.selectCount(wrapper);
        if (count > 0) {
            return;
        }
        // 保存交易记录
        PaymentInfo paymentInfo = new PaymentInfo();
        paymentInfo.setCreateTime(new Date());
        paymentInfo.setOrderId(orderInfo.getId());
        paymentInfo.setPaymentType(paymentType);
        paymentInfo.setOutTradeNo(orderInfo.getOutTradeNo());
        paymentInfo.setPaymentStatus(PaymentStatus.UNPAID.name());
        paymentInfo.setSubject(orderInfo.getTradeBody());
        paymentInfo.setSubject("test");
//        paymentInfo.setSubject(orderInfo.getTradeBody());
        paymentInfo.setTotalAmount(orderInfo.getTotalAmount());

        paymentInfoMapper.insert(paymentInfo);
    }

    /**
     * 查询支付状态
     *
     * @param out_trade_no
     * @param name
     * @return
     */
    @Override
    public PaymentInfo getPaymentInfo(String out_trade_no, String name) {

        QueryWrapper<PaymentInfo> paymentInfoQueryWrapper = new QueryWrapper<>();
        paymentInfoQueryWrapper.eq("out_trade_no", out_trade_no);
        paymentInfoQueryWrapper.eq("payment_type", name);
        return paymentInfoMapper.selectOne(paymentInfoQueryWrapper);
    }

    /**
     * 更新交易记录
     *
     * @param out_trade_no
     * @param name
     * @param paramMap
     */
    @Override
    public void paySuccess(String out_trade_no, String name, Map<String, String> paramMap) {

//        查询交易状态
        PaymentInfo paymentIfo = paymentService.getPaymentInfo(out_trade_no, name);

//        判断交易是否关闭
        if ("CLOSED".equals(paymentIfo.getPaymentStatus()) || "PAID".equals(paymentIfo.getPaymentStatus())){
            return;
        }

        PaymentInfo paymentInfo = new PaymentInfo();
        paymentInfo.setTradeNo(paramMap.get("trade_no"));
        paymentInfo.setCallbackTime(new Date());
        paymentInfo.setPaymentStatus(PaymentStatus.PAID.name());
        paymentInfo.setCallbackContent(paramMap.toString());

        this.updatePaymentInfo(out_trade_no, name, paymentInfo);

//        发送消息更改订单状态
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_PAY,MqConst.ROUTING_PAYMENT_PAY,paymentIfo.getOrderId());

    }

    /**
     * 方法复用
     *
     * @param outTradeNo
     * @param name
     * @param paymentInfo
     */
    public void updatePaymentInfo(String outTradeNo, String name, PaymentInfo paymentInfo) {
        QueryWrapper<PaymentInfo> paymentInfoQueryWrapper = new QueryWrapper<>();
        paymentInfoQueryWrapper.eq("out_trade_no", outTradeNo);
        paymentInfoQueryWrapper.eq("payment_type", name);
        // 第一个参数表示啥?要更新的内容  第二个参数表示啥？
        paymentInfoMapper.update(paymentInfo, paymentInfoQueryWrapper);
    }

    /**
     * 退款
     *
     * @param orderId
     * @return
     */
    @Override
    public Boolean refund(Long orderId) {
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();

//        查询订单详情
        OrderInfo orderInfo = orderFeignClient.getOrderInfo(orderId);
        HashMap<String, Object> map = new HashMap<>();
        map.put("out_trade_no", orderInfo.getOutTradeNo());
        map.put("refund_amount", "0.01");
        map.put("refund_reason", "颜色浅了点");
//        提交参数
        request.setBizContent(JSON.toJSONString(map));
        AlipayTradeRefundResponse response = null;
        try {
            response = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        if (response.isSuccess()) {
            // 更新交易记录 ： 关闭
            PaymentInfo paymentInfo = new PaymentInfo();
            paymentInfo.setPaymentStatus(PaymentStatus.ClOSED.name());
            paymentService.updatePaymentInfo(orderInfo.getOutTradeNo(), PaymentType.ALIPAY.name(), paymentInfo);

//            关闭订单交易
            OrderInfo orderInfo1 = new OrderInfo();


            return true;
        }
        return false;
    }

    /**
     *         关闭支付交易
     * @param orderId
     */
    @Override
    public void closePayInfo(Long orderId) {

        UpdateWrapper<PaymentInfo> wrapper = new UpdateWrapper<>();
        wrapper.eq("order_id",orderId);
//        判断是否存在交易记录
        Integer count = paymentInfoMapper.selectCount(wrapper);
        if (count==0){
            return;
        }
//            关闭支付状态
        PaymentInfo paymentInfo = new PaymentInfo();
        paymentInfo.setPaymentStatus(PaymentStatus.ClOSED.name());
        paymentInfoMapper.update(paymentInfo,wrapper);
    }
}
